In [1]:
import pandas as pd
import networkx as nx
import seaborn as sns
import numpy as np
import benford as bf
pd.options.display.float_format = '{:.2f}'.format
In [2]:
import matplotlib.pyplot as plt
%matplotlib inline
rc={'savefig.dpi': 75, 'figure.autolayout': False, 'figure.figsize': [12, 8], 'axes.labelsize': 18,\
'axes.titlesize': 18, 'font.size': 18, 'lines.linewidth': 2.0, 'lines.markersize': 8, 'legend.fontsize': 16,\
'xtick.labelsize': 16, 'ytick.labelsize': 16}
sns.set(style='whitegrid',rc=rc)
In [3]:
comites_brasil = pd.read_csv("C:/Users/felip/Dropbox/ufrgs/phd/Barbosa-Gammerman/Estudos/chrimatocracy/data/2014/receitas_comites_2014_brasil.txt", encoding="ISO-8859-1", sep=';', na_values = '#NULO', dtype=str)
corruptos_brasil = pd.read_csv("C:/Users/felip/Dropbox/ufrgs/phd/Barbosa-Gammerman//Estudos/chrimatocracy/data/2014/receitas_candidatos_2014_brasil.txt", encoding="ISO-8859-1", sep=';', na_values = '#NULO', dtype=str)
partidos_brasil = pd.read_csv("C:/Users/felip/Dropbox/ufrgs/phd/Barbosa-Gammerman/Estudos/chrimatocracy/data/2014/receitas_partidos_2014_brasil.txt", encoding="ISO-8859-1", sep=';', na_values = '#NULO', dtype=str)
In [4]:
comites_brasil["Valor receita"] = comites_brasil["Valor receita"].str.replace(',', '.').apply(float)
partidos_brasil["Valor receita"] = partidos_brasil["Valor receita"].str.replace(',', '.').apply(float)
corruptos_brasil["Valor receita"] = corruptos_brasil["Valor receita"].str.replace(',', '.').apply(float)
In [5]:
print("Número total de doações a partidos:", partidos_brasil['Sigla Partido'].count())
In [6]:
print("Número de partidos que receberam doações:", partidos_brasil['Sigla Partido'].nunique())
In [7]:
diretas_part_pj = partidos_brasil[(partidos_brasil[u'CPF/CNPJ do doador originário'].isnull()) & (partidos_brasil[u'CPF/CNPJ do doador'].str.len() == 14)]
print("Número de doações diretas de empresas a partidos:",diretas_part_pj['Sigla Partido'].count())
print("Valor: R$",'%.1e' % diretas_part_pj["Valor receita"].sum())
In [8]:
diretas_part_pf = partidos_brasil[(partidos_brasil[u'CPF/CNPJ do doador originário'].isnull()) & (partidos_brasil[u'CPF/CNPJ do doador'].str.len() == 11)]
print("Número de doações diretas de indivíduos a partidos:",diretas_part_pf['Sigla Partido'].count())
print("Valor: R$",'%.1e' % diretas_part_pf["Valor receita"].sum())
In [9]:
indiretas_part_pj = partidos_brasil[(partidos_brasil[u'CPF/CNPJ do doador originário'].str.len() == 14) & (partidos_brasil[u'CPF/CNPJ do doador'].str.len() == 14)]
print("Número de doações indiretas provenientes de empresas a partidos:",indiretas_part_pj['Sigla Partido'].count())
print("Valor: R$",'%.1e' % indiretas_part_pj["Valor receita"].sum())
In [10]:
indiretas_part_pf = partidos_brasil[(partidos_brasil[u'CPF/CNPJ do doador originário'].str.len() == 11) & (partidos_brasil[u'CPF/CNPJ do doador'].str.len() == 14)]
print("Número de doações indiretas provenientes de individuos a partidos:",indiretas_part_pf['Sigla Partido'].count())
print("Valor: R$",'%.1e' % indiretas_part_pf["Valor receita"].sum())
In [11]:
unknow_part = partidos_brasil[(partidos_brasil[u'Nome do doador origin\xe1rio'].isnull()) & (partidos_brasil[u'CPF/CNPJ do doador'].isnull())]
#doador_brasil.drop(unknow.index, inplace=True)
print("Número de doações não rastreadas a partidos",unknow_part['Sigla Partido'].count())
print("Valor: R$",'%.1e' % unknow_part["Valor receita"].sum())
In [12]:
comites_brasil["Tipo Comite"].unique()
Out[12]:
In [13]:
print("Número total de doações a comites:", comites_brasil['Sequencial Comite'].count())
In [14]:
print("Número de comites que receberam doações:",comites_brasil['Sequencial Comite'].nunique())
In [15]:
diretas_com_pj = comites_brasil[(comites_brasil[u'CPF/CNPJ do doador originário'].isnull()) & (comites_brasil[u'CPF/CNPJ do doador'].str.len() == 14)]
print("Número de doações diretas de empresas a comites:",diretas_com_pj["Sequencial Comite"].count())
print("Valor: R$",'%.1e' % diretas_com_pj["Valor receita"].sum())
In [16]:
diretas_com_pf = comites_brasil[(comites_brasil[u'CPF/CNPJ do doador originário'].isnull()) & (comites_brasil[u'CPF/CNPJ do doador'].str.len() == 11)]
print("Número de doações diretas de indivíduos a comites:",diretas_com_pf["Sequencial Comite"].count())
print("Valor: R$",'%.1e' % diretas_com_pf["Valor receita"].sum())
In [17]:
indiretas_com_pj = comites_brasil[(comites_brasil[u'CPF/CNPJ do doador originário'].str.len() == 14) & (comites_brasil[u'CPF/CNPJ do doador'].str.len() == 14)]
print("Número de doações indiretas provenientes de empresas a comites:",indiretas_com_pj["Sequencial Comite"].count())
print("Valor: R$",'%.1e' % indiretas_com_pj["Valor receita"].sum())
In [18]:
indiretas_com_pf = comites_brasil[(comites_brasil[u'CPF/CNPJ do doador originário'].str.len() == 11) & (comites_brasil[u'CPF/CNPJ do doador'].str.len() == 14)]
print("Número de doações indiretas provenientes de individuos a comites:",indiretas_com_pf["Sequencial Comite"].count())
print("Valor: R$",'%.1e' % indiretas_com_pf["Valor receita"].sum())
In [19]:
unknow_com = comites_brasil[(comites_brasil[u'Nome do doador origin\xe1rio'].isnull()) & (comites_brasil[u'CPF/CNPJ do doador'].isnull())]
#doador_brasil.drop(unknow.index, inplace=True)
print("Número de doações não rastreadas a comites",unknow_com["Sequencial Comite"].count())
print("Valor: R$",'%.1e' % unknow_com["Valor receita"].sum())
In [20]:
doador_brasil=corruptos_brasil[(corruptos_brasil["Cargo"] == "Deputado Estadual")]
print("Cargos filtrados:", doador_brasil["Cargo"].unique())
In [21]:
print("Número total de doações:", doador_brasil['CPF do candidato'].count())
In [22]:
print("Número de candidatos que receberam doações:",doador_brasil['CPF do candidato'].nunique())
In [23]:
diretas_pj = doador_brasil[(doador_brasil[u'CPF/CNPJ do doador originário'].isnull()) & (doador_brasil[u'CPF/CNPJ do doador'].str.len() == 14)]
print("Número de doações diretas de empresas:",diretas_pj["CPF do candidato"].count())
print("Valor: R$",'%.1e' % diretas_pj["Valor receita"].sum())
In [24]:
diretas_pf = doador_brasil[(doador_brasil[u'CPF/CNPJ do doador originário'].isnull()) & (doador_brasil[u'CPF/CNPJ do doador'].str.len() == 11)]
print("Número de doações diretas de indivíduos:",diretas_pf["CPF do candidato"].count())
print("Valor: R$",'%.1e' % diretas_pf["Valor receita"].sum())
In [25]:
indiretas_pj = doador_brasil[(doador_brasil[u'CPF/CNPJ do doador originário'].str.len() == 14) & (doador_brasil[u'CPF/CNPJ do doador'].str.len() == 14)]
print("Número de doações indiretas provenientes de empresas:",indiretas_pj["CPF do candidato"].count())
print("Valor: R$",'%.1e' % indiretas_pj["Valor receita"].sum())
In [26]:
indiretas_pf = doador_brasil[(doador_brasil[u'CPF/CNPJ do doador originário'].str.len() == 11) & (doador_brasil[u'CPF/CNPJ do doador'].str.len() == 14)]
print("Número de doações indiretas provenientes de individuos:",indiretas_pf["CPF do candidato"].count())
print("Valor: R$",'%.1e' % indiretas_pf["Valor receita"].sum())
In [27]:
indiretas_teste = doador_brasil[(doador_brasil[u'CPF/CNPJ do doador originário'].isnull() == False) & (doador_brasil[u'CPF/CNPJ do doador'].str.len() == 11)]
print("Número de doações com intermediário sendo uma pessoa física",indiretas_teste["CPF do candidato"].count())
print("Valor: R$",'%.1e' % indiretas_teste["Valor receita"].sum())
if indiretas_teste["CPF do candidato"].count() == 0 :print("UFA!")
In [28]:
unknow = doador_brasil[(doador_brasil[u'Nome do doador origin\xe1rio'].isnull()) & (doador_brasil[u'CPF/CNPJ do doador'].isnull())]
#doador_brasil.drop(unknow.index, inplace=True)
print("Número de doações não rastreadas",unknow["CPF do candidato"].count())
print("Valor: R$",'%.1e' % unknow["Valor receita"].sum())
Criamos uma coluna doador que, mapeia o doador intermediário no doador originário nos casos onde esse é nulo. O objetivo é que essa coluna possua a informação do doador original nos casos de repasse e o próprio doador nos casos de doações diretas.
In [29]:
doador = doador_brasil[u'CPF/CNPJ do doador originário'].fillna(doador_brasil[u'CPF/CNPJ do doador'])
In [30]:
doador_brasil = doador_brasil.assign(doador = doador.values)
doador_brasil.to_csv("C:/Users/felip/Dropbox/ufrgs/phd/Barbosa-Gammerman/Estudos/network/data/doador_dep_estadual_brasil.csv")
Estatística básica das doações
In [31]:
stats_donations = pd.DataFrame(doador_brasil['Valor receita'].describe()).T.append(\
pd.DataFrame(doador_brasil[doador_brasil['doador'].str.len() == 14]['Valor receita'].describe()).T.append(\
pd.DataFrame(doador_brasil[doador_brasil['doador'].str.len() == 11]['Valor receita'].describe()).T))
stats_donations.index = ['Todos','CNPJ','CPF']
stats_donations.columns = ['N', 'Média', 'DP', 'Min', '25%', "50%", '75%', 'Max']
stats_donations
#print(stats_donations.to_latex())
Out[31]:
In [32]:
doador_brasil[doador_brasil['Valor receita'] == 2000000]["Nome candidato"]
Out[32]:
In [33]:
doador_brasil['dia'], doador_brasil["mes"] = doador_brasil["Data da receita"].str.split("/").apply(lambda x: x[0]), \
doador_brasil["Data da receita"].str.split("/").apply(lambda x: x[1])
In [34]:
doador_brasil.to_csv("/Users/felip/doador_brasil.csv")
In [35]:
import numpy as np
import matplotlib.pyplot as plt
# method 1
H2,X2 = np.histogram( np.log10(doador_brasil['Valor receita']), normed = True )
dx2 = X2[1] - X2[0]
F2 = np.cumsum(H2)*dx2
plt.fill_between(X2[1:], F2,facecolor="#1DACD6", alpha=.7)
plt.plot(X2[1:], F2, c='#1DACD6', linestyle='-')
plt.ylabel("CDF")
plt.xlabel('ln(Valor(R$))')
plt.title("Todos")
plt.legend()
plt.grid(False)
plt.tight_layout()
#plt.savefig('/Estudos/chrimatocracy/figures/cdf_receita_brasil_dep_estadual_all.pdf')
plt.show()
In [36]:
import numpy as np
import matplotlib.pyplot as plt
# method 1
H2,X2 = np.histogram( np.log10(doador_brasil[doador_brasil['doador'].str.len() == 14]['Valor receita']), normed = True )
dx2 = X2[1] - X2[0]
F2 = np.cumsum(H2)*dx2
plt.plot(X2[1:], F2, c='#1DACD6', linestyle='-')
plt.fill_between(X2[1:], F2,facecolor="#1DACD6", alpha=.7)
plt.ylabel("CDF")
plt.xlabel('ln(Valor(R$))')
plt.title("Pessoa Jurídica")
plt.legend()
plt.grid(False)
plt.tight_layout()
#plt.savefig('/Estudos/chrimatocracy/figures/cdf_receita_brasil_dep_estadual_cnpj.pdf')
In [37]:
import numpy as np
import matplotlib.pyplot as plt
# method 1
H2,X2 = np.histogram( np.log10(doador_brasil[doador_brasil['doador'].str.len() == 11]['Valor receita']), normed = True )
dx2 = X2[1] - X2[0]
F2 = np.cumsum(H2)*dx2
plt.plot(X2[1:], F2, c='#1DACD6', linestyle='-')
plt.fill_between(X2[1:], F2,facecolor="#1DACD6", alpha=.7)
plt.ylabel("CDF")
plt.xlabel('ln(Valor(R$))')
plt.title("Pessoa Física")
plt.legend()
plt.grid(False)
plt.tight_layout()
#plt.savefig('/Estudos/chrimatocracy/figures/cdf_receita_brasil_dep_estadual_cpf.pdf')
Somamos os valores provenientes de um mesmo doador para um dado candidato (mais de uma doação ou repasse de doações oriundas desse doador)
In [38]:
aggregations = {
u"Valor receita": 'sum'
}
doador_candidato = doador_brasil.groupby([u'CPF do candidato','doador','Sigla Partido', 'Cargo', "UF"]).agg(aggregations)
doador_candidato = pd.DataFrame(doador_candidato)
doador_candidato = doador_candidato.reset_index()
In [39]:
print("Número de empresas que doaram, direta ou indiretamente, para candidatos",doador_candidato[doador_candidato['doador'].str.len()==14]['Valor receita'].count())
print("Valor: R$",'%.1e' % doador_candidato[doador_candidato['doador'].str.len()==14]['Valor receita'].sum())
In [40]:
print("Número de indivíduos que doaram, direta ou indiretamente, para candidatos",doador_candidato[doador_candidato['doador'].str.len()==11]['Valor receita'].count())
print("Valor: R$",'%.1e' % doador_candidato[doador_candidato['doador'].str.len()==11]['Valor receita'].sum())
Box-plot do valor das doações em escala logaritmica, feitas para candidatos, agregadas por partido. Os valores abragem aproximadamente 7 escalas de grandeza mas possuem valores médios similares.
In [41]:
g = sns.boxplot(x="Sigla Partido", y="Valor receita", data=doador_candidato, color = '#1DACD6')
plt.yscale('log')
plt.xticks(rotation=90)
plt.grid(False)
plt.tight_layout()
#plt.savefig("/Estudos/chrimatocracy/figures/receita_box_dep_estadual_partido.pdf")
A tabela de candidatos possui informações sobre o perfil dos candidatos,tais como raça, escolaridade, estado civil, além das informações relacionadas às eleições. Além disso, para associarmos a lista de votação à lista de doações, precisamos da informação sobre o CPF, que só consta na tabela de candidatos. Esse mapeamento somente pode ser feito através da sequencial, constante tanto na tabela de candidatos quando na de votos.
In [42]:
legenda_cantidatos = ['DATA_GERACAO', 'HORA_GERACAO', 'ANO_ELEICAO', 'NUM_TURNO',\
'DESCRICAO_ELEICAO', 'SIGLA_UF', 'SIGLA_UE', 'DESCRICAO_UE',\
'CODIGO_CARGO', 'DESCRICAO_CARGO', 'NOME_CANDIDATO',\
'SEQUENCIAL_CANDIDATO', 'NUMERO_CANDIDATO', 'CPF_CANDIDATO',\
'NOME_URNA_CANDIDATO', 'COD_SITUACAO_CANDIDATURA',\
'DES_SITUACAO_CANDIDATURA', 'NUMERO_PARTIDO', 'SIGLA_PARTIDO',\
'NOME_PARTIDO', 'CODIGO_LEGENDA', 'SIGLA_LEGENDA', 'COMPOSICAO_LEGENDA',\
'NOME_LEGENDA', 'CODIGO_OCUPACAO', 'DESCRICAO_OCUPACAO',\
'DATA_NASCIMENTO', 'NUM_TITULO_ELEITORAL_CANDIDATO',\
'IDADE_DATA_ELEICAO', 'CODIGO_SEXO', 'DESCRICAO_SEXO',\
'COD_GRAU_INSTRUCAO', 'DESCRICAO_GRAU_INSTRUCAO', 'CODIGO_ESTADO_CIVIL',\
'DESCRICAO_ESTADO_CIVIL', 'CODIGO_COR_RACA', 'DESCRICAO_COR_RACA',\
'CODIGO_NACIONALIDADE', 'DESCRICAO_NACIONALIDADE',\
'SIGLA_UF_NASCIMENTO', 'CODIGO_MUNICIPIO_NASCIMENTO',\
'NOME_MUNICIPIO_NASCIMENTO', 'DESPESA_MAX_CAMPANHA',\
'COD_SIT_TOT_TURNO', 'DESC_SIT_TOT_TURNO', 'NM_EMAIL']
In [43]:
import glob, os
candidatos_brasil = pd.DataFrame()
path_2014 = 'C:/Users/felip/Dropbox/ufrgs/phd/Barbosa-Gammerman/Estudos/chrimatocracy/data/2014/cadidatos/'
allFiles = glob.glob(os.path.join(path_2014, "consulta_cand_2014_*"))
candidatos_brasil = pd.concat((pd.read_csv(f, header=None, names=legenda_cantidatos, encoding="ISO-8859-1", sep=';', na_values = '#NULO#') for f in allFiles))
Filtramos candidatos para os cargos estudos, cuja candidatura foi deferida
In [44]:
indeferidos_candidatos = candidatos_brasil[(candidatos_brasil['DES_SITUACAO_CANDIDATURA'] != "DEFERIDO") & ((candidatos_brasil['CODIGO_CARGO'] == 7))]
print("Cargos:", indeferidos_candidatos["DESCRICAO_CARGO"].unique())
print("Número de canidatos indeferidos",indeferidos_candidatos["SEQUENCIAL_CANDIDATO"].nunique())
In [45]:
candidatos_brasil_def = candidatos_brasil[(candidatos_brasil['DES_SITUACAO_CANDIDATURA'] == "DEFERIDO") & ((candidatos_brasil['CODIGO_CARGO'] == 7))]
print("Cargos:", candidatos_brasil_def["DESCRICAO_CARGO"].unique())
print("Número de candidatos deferidos",candidatos_brasil_def["SEQUENCIAL_CANDIDATO"].nunique())
In [46]:
import gc
#del candidatos_brasil
#del corruptos_brasil
#del comites_brasil
#del partidos_brasil
gc.collect()
Out[46]:
Criamos a lista de candidatos baseado na sua sequencial, utilizada para cruzar essa base de informações com a base votação.
In [47]:
list_cand = candidatos_brasil_def["SEQUENCIAL_CANDIDATO"].unique()
print("Número de candidatos na lista:",len(list_cand))
A tabela de votos possui informação sobre os dados apurados da votação, no primeiro e segundo turno, em cada munício, além de informações eleitorias.
In [48]:
legenda_votos = ['DATA_GERACAO', 'HORA_GERACAO', 'ANO_ELEICAO', 'NUM_TURNO',\
'DESCRICAO_ELEICAO', 'SIGLA_UF', 'SIGLA_UE', 'CODIGO_MUNICIPIO',\
'NOME_MUNICIPIO', 'NUMERO_ZONA', 'CODIGO_CARGO', 'NUMERO_CAND',\
'SQ_CANDIDATO', 'NOME_CANDIDATO', 'NOME_URNA_CANDIDATO',\
'DESCRICAO_CARGO', 'COD_SIT_CAND_SUPERIOR', 'DESC_SIT_CAND_SUPERIOR',\
'CODIGO_SIT_CANDIDATO', 'DESC_SIT_CANDIDATO', 'CODIGO_SIT_CAND_TOT',\
'DESC_SIT_CAND_TOT', 'NUMERO_PARTIDO', 'SIGLA_PARTIDO', 'NOME_PARTIDO',\
'SEQUENCIAL_LEGENDA', 'NOME_COLIGACAO', 'COMPOSICAO_LEGENDA',\
'TOTAL_VOTOS', 'TRANSITO']
In [49]:
votes_brasil = pd.DataFrame()
path_2014 = 'C:/Users/felip/Dropbox/ufrgs/phd/Barbosa-Gammerman/Estudos/chrimatocracy/data/2014/votacao/'
allFiles = glob.glob(os.path.join(path_2014, "votacao_candidato_munzona_2014_*"))
votes_brasil = pd.concat((pd.read_csv(f, header=None, names=legenda_votos, encoding="ISO-8859-1", sep=';', na_values = '#NULO#') for f in allFiles))
In [50]:
indeferidos = votes_brasil[((votes_brasil["CODIGO_CARGO"] == 7)) & (votes_brasil["DESC_SIT_CANDIDATO"] != "DEFERIDO")]
print("Cargos:", indeferidos["DESCRICAO_CARGO"].unique())
print("Número de canidatos indeferidos",indeferidos["SQ_CANDIDATO"].nunique())
In [51]:
votos_dep_brasil = votes_brasil[((votes_brasil["CODIGO_CARGO"] == 7) ) & (votes_brasil["DESC_SIT_CANDIDATO"] == "DEFERIDO")]
print("Cargos:", votos_dep_brasil["DESCRICAO_CARGO"].unique())
print("Número de canidatos deferidos",votos_dep_brasil["SQ_CANDIDATO"].nunique())
In [52]:
import gc
del votes_brasil
del candidatos_brasil
del corruptos_brasil
del comites_brasil
del partidos_brasil
gc.collect()
Out[52]:
Percebemos que há um candidato a mais do que o da lista de candidatos. É um fato curioso um candidato receber votos, mas não constar na lista inicial. Trata-se de Tâmara Joana Biolo Soares, que não foi eleita.
In [53]:
votos_dep_brasil[votos_dep_brasil["SQ_CANDIDATO"].isin(list_cand)==False].groupby(["NOME_CANDIDATO",'DESC_SIT_CAND_TOT']).agg({"TOTAL_VOTOS":sum}).reset_index()
Out[53]:
Criamos a lista de sequenciais dessa tabela
In [54]:
list_votes = votos_dep_brasil["SQ_CANDIDATO"].unique()
print("Número de sequenciais:", len(list_votes))
In [55]:
merged_df = pd.merge(votos_dep_brasil, candidatos_brasil_def, left_on='SQ_CANDIDATO', right_on="SEQUENCIAL_CANDIDATO",how='left', sort=False, suffixes=("_votes", "_candidatos"))
print("Número de sequenciais após o merge:", merged_df['SQ_CANDIDATO'].nunique())
Selecionamos colunas relevantes e eliminando duplicidades.
In [56]:
selec_merged_df=merged_df[['NUM_TURNO_votes', 'SIGLA_UF_votes',\
'SIGLA_UE_votes', 'CODIGO_MUNICIPIO', 'NOME_MUNICIPIO', 'NUMERO_ZONA',\
'CODIGO_CARGO_votes', 'NUMERO_CAND', 'SQ_CANDIDATO', 'NOME_CANDIDATO_votes',\
'NUMERO_PARTIDO_votes', 'SIGLA_PARTIDO_votes', 'NOME_PARTIDO_votes', \
'SEQUENCIAL_LEGENDA', 'NOME_COLIGACAO',\
'COMPOSICAO_LEGENDA_votes', 'TOTAL_VOTOS', \
'SEQUENCIAL_CANDIDATO', 'NUMERO_CANDIDATO', 'CPF_CANDIDATO',\
'CODIGO_LEGENDA', 'SIGLA_LEGENDA',\
'COMPOSICAO_LEGENDA_candidatos',"DESPESA_MAX_CAMPANHA",'CODIGO_SIT_CAND_TOT', 'DESC_SIT_CAND_TOT']]
In [57]:
import gc
del merged_df
gc.collect()
Out[57]:
Vamos criar uma tabela contendo informações do canditato, com o número de votos por munícipio somados.
In [58]:
cpf_votos = selec_merged_df.groupby(["CPF_CANDIDATO",'DESC_SIT_CAND_TOT','SIGLA_UF_votes',\
'NOME_CANDIDATO_votes','COMPOSICAO_LEGENDA_votes','SIGLA_PARTIDO_votes'])\
.agg({'TOTAL_VOTOS':'sum'}).reset_index()
#cpf_votos.to_csv("/Estudos/network/data/cpf_votos_dep_estadual_brasil.csv")
Aqui é interessante comparar alguns números com os obtidos por outra fonte de informação, obtida em http://www.tse.jus.br/eleicoes/estatisticas/estatisticas-candidaturas-2014/estatisticas-eleitorais-2014-eleitorado
In [61]:
votos_estadual_tse = pd.read_csv('C:/Users/felip/Dropbox/ufrgs/phd/Barbosa-Gammerman/Estudos/chrimatocracy/data/2014/tse_votacao/resultado_dep_estadual.csv', encoding="ISO-8859-1", sep=';', na_values = '#NULO')
dep_estadual_votacao = votos_estadual_tse[["Candidato", "Votação", "Situação"]]
print("Número de candidatos:",dep_estadual_votacao["Candidato"].nunique())
print("Número de candidatos eleitos:", dep_estadual_votacao["Situação"][dep_estadual_votacao["Situação"].isin(["Eleito por QP", "Eleito por média"])].count())
O número obtido, 308, correponde aos 305 encontrados no merge mais os 3 indeferidos.
Vamos reunir as informações de perfil e votação, com as informações sobre as doações. Iremos fazer isso através do uso do CPF do candidato. Ambmas informações precisam ser do mesmo tipo.
In [62]:
doador_brasil.loc[:,'CPF do candidato'] = doador_brasil['CPF do candidato'].apply(lambda x: int(x))
cpf_votos.loc[:,'CPF_CANDIDATO'] = cpf_votos['CPF_CANDIDATO'].apply(lambda x: int(x))
print("Número de candidatos que receberam doações:",doador_brasil['CPF do candidato'].nunique())
print("Número de candidatos que receberam votos:",cpf_votos['CPF_CANDIDATO'].nunique())
Antes de reunir a informação, vamos verificar o que devemos esperar. Para isso criamos uma lista dos CPFs contidos em cada uma delas.
In [63]:
list_doador = doador_brasil[u"CPF do candidato"].unique()
list_votos = cpf_votos['CPF_CANDIDATO'].unique()
Primeiro vamos verificar candidatos que receberam doações e mas não constam nem lista de candidatos, nem na lista de votos. Candidato que não receberam votos (nem seu próprio voto?) parecem fazer parte dessa lista.
In [64]:
nem_nem = doador_brasil[doador_brasil['CPF do candidato'].isin(list_votos)==False]
print("Número de candidatos que estão na lista de doações, mas não nas outras:", nem_nem['CPF do candidato'].nunique())
print("Valor:",nem_nem["Valor receita"].sum())
#print("Candidatos:", list(nem_nem['Nome candidato'].unique()))
Optamos por não remover essas doações, pois elas parecem ser extramente suspeitas.
In [65]:
#doador_brasil.drop(nem_nem.index, inplace=True, errors='ignore')
Vamos verificar quais os candidatos não receberam doações.
In [66]:
none_donation = cpf_votos[cpf_votos['CPF_CANDIDATO'].isin(list_doador)==False]
print("Número de candidatos não receberam doações:", none_donation['CPF_CANDIDATO'].nunique())
Vamos reunir inserir essa informação de maneira artifical na tabela de doações, apenas para análise do valor da receita recebida por esse candidatos, 0.
In [67]:
#none_donation= none_donation.assign(Valor= 0)
In [68]:
#none_donation.columns = ["CPF do candidato", 'DESC_SIT_CAND_TOT','SIGLA_UF_votes','NOME_CANDIDATO_votes', "COMPOSICAO_LEGENDA_votes", "Sigla Partido", "TOTAL_VOTOS", "Valor receita"]
Primeiro criamos uma tabela com as doações individuais. Nessa tabela, as informações do candidato estão repetidas, inclusive os votos recebidos.
In [69]:
merged_receitas = pd.merge(doador_brasil, cpf_votos, left_on='CPF do candidato', right_on="CPF_CANDIDATO",how='left', sort=False)
In [70]:
#merged_receitas = merged_receitas.append(none_donation)
#merged_receitas.to_csv("/Estudos/network/data/merged_receitas_dep_estadual_brasil.csv")
Em seguida criamos uma tabela com as doações agregadas. Nela há o total das doações recebidas do candidato, assim como o número de votos do mesmo.
In [71]:
merged_votos = merged_receitas.groupby(["Sigla Partido",'CPF do candidato','SIGLA_UF_votes', 'NOME_CANDIDATO_votes',"COMPOSICAO_LEGENDA_votes","DESC_SIT_CAND_TOT"]).agg({"TOTAL_VOTOS":lambda x: sum(x)/len(x), "Valor receita":'sum'}).\
reset_index()
#merged_votos.to_csv("/Estudos/network/data/merged_votos_dep_estadual_brasil.csv")
In [72]:
sns.countplot(x='DESC_SIT_CAND_TOT', data=merged_votos, color = "#1DACD6")
plt.xlabel("Situação")
plt.ylabel("")
plt.grid(False)
plt.tight_layout()
#plt.savefig('/Estudos/chrimatocracy/figures/situacao_brasil_dep_estadual.pdf')
Vamos verificar se a distribuição das receitas adere à lei de Benford.
In [73]:
import matplotlib
all_digits = bf.read_numbers(doador_brasil["Valor receita"])
all_probs = bf.find_probabilities(all_digits)
x2 = bf.find_x2(pd.Series(all_digits))
width = 0.2
indx = np.arange(1, len(all_probs) + 1)
benford = [np.log10(1 + (1.0 / d)) for d in indx]
plt.bar(indx, benford,width, color='r', label="Lei de Benford",)
plt.bar(indx+width , all_probs, width, color='#1DACD6', label=r'Doações($\chi^2$''='+str(round(x2,2))+')')
plt.yscale('log')
plt.xscale('log')
ax = plt.gca()
ax.set_xticks(indx)
ax.set_yticks([0.05,0.1, 0.2, 0.3])
ax.get_xaxis().set_major_formatter(matplotlib.ticker.ScalarFormatter())
ax.get_yaxis().set_major_formatter(matplotlib.ticker.ScalarFormatter())
plt.title("Deputado Estadual")
plt.ylabel("Probabilidade")
plt.grid(False)
plt.legend()
plt.tight_layout()
#plt.savefig("/Estudos/chrimatocracy/figures/benford_dep_estadual_brasil.pdf")
plt.show()
Vamos verificar, utilizando um modelo de regressão logística, se o valor recebido através das doações, é um importante preditor para a eleição de um candidato.
In [74]:
import pandas as pd
In [75]:
#merged_votos = pd.read_csv('/Estudos/network/data/merged_votos_dep_estadual_brasil.csv')
In [76]:
import statsmodels.api as sm
import numpy as np
params = []
params2 = []
estados = merged_votos['SIGLA_UF_votes'].unique()
final = pd.DataFrame()
for uf in estados:
X = merged_votos[merged_votos['SIGLA_UF_votes']==uf].set_index("CPF do candidato")[['Valor receita','DESC_SIT_CAND_TOT']]
soma = X['Valor receita'].sum()
X['Valor receita'] = X['Valor receita'].apply(lambda x: x/soma)
y=X["DESC_SIT_CAND_TOT"].apply(lambda x: 1 if (x=="ELEITO POR QP" or x=="ELEITO POR MÉDIA") else 0)
X.drop('DESC_SIT_CAND_TOT', axis=1,inplace=True)
X_1 = np.append( np.ones((X.shape[0], 1)), X, axis=1)
logit = sm.Logit(y, X_1)
result = logit.fit()
odds = np.exp(float(result.params.values[1]) * 100000/soma)
sumar = result.summary2()
llrp = sumar.tables[0][3][5]
params = pd.DataFrame(sumar.tables[1].loc["x1"].values[0:4], index=["Coeficiente", 'Desvio Padrão','z', "p-valor"]).T
params["beta"] = r'\beta_1'
params["LLR p"] = llrp
params["Odds ratio"] = odds
params["Estado"] = uf
params["Valor"] = merged_votos[merged_votos['SIGLA_UF_votes']==uf]["Valor receita"].sum()
params["N"] = merged_votos[merged_votos['SIGLA_UF_votes']==uf]["DESC_SIT_CAND_TOT"].count()
params["n"] = merged_votos[merged_votos['SIGLA_UF_votes']==uf]["DESC_SIT_CAND_TOT"].apply(lambda x: 1 if (x=="ELEITO POR QP" or x=="ELEITO POR MÉDIA") else 0).sum()
final = final.append(params)
params2 = pd.DataFrame(sumar.tables[1].loc["const"].values[0:4], index=["Coeficiente", 'Desvio Padrão','z', "p-valor"]).T
params2["beta"] = r'\beta_0'
params2["LLR p"] = llrp
params2["Odds ratio"] = odds
params2["Estado"] = uf
params2["Valor"] = merged_votos[merged_votos['SIGLA_UF_votes']==uf]["Valor receita"].sum()
params2["N"] = merged_votos[merged_votos['SIGLA_UF_votes']==uf]["DESC_SIT_CAND_TOT"].count()
params2["n"] = merged_votos[merged_votos['SIGLA_UF_votes']==uf]["DESC_SIT_CAND_TOT"].apply(lambda x: 1 if (x=="ELEITO POR QP" or x=="ELEITO POR MÉDIA") else 0).sum()
final = final.append(params2)
In [77]:
fitTab = final.sort_values(by="Estado").set_index("Estado").reset_index()
fitTab = final.set_index(["Estado", "LLR p", "Odds ratio" , "Valor", "N", "n", "beta"])
#print(fitTab.to_latex())
fitTab
Out[77]:
Vamos obter a odds ratio exponenciando o coeficiente obtido. Esse parâmetro nos diz como o incremento ou decremento de uma unidade na variável explicativa afeta as chances do candadito ser eleito. Podemos desfazer a normalização adotada para entender a importância do dinheiro para a variável resposta.
In [122]:
for j,i in zip(final['Estado'].unique(), final['Odds ratio'].unique()):
print("Cada R$ 100.000 aumenta as chances de um deputado do ",j," ser eleito em", '%.2f'% float((i-1)*100), "%")
In [ ]: